---------The Friendly Computer---------
A 4am crack                  2017-03-23
---------------------------------------

Name: The Friendly Computer
Version: 1.0
Genre: educational
Year: 1983
Publisher: MECC
Platform: Apple ][+ or later
Media: single-sided 5.25-inch disk
OS: DOS 3.3 variant
Previous cracks: none (of this version)

                   ~

               Chapter 0
   In Which Various Automated Tools
      Succeed In Interesting Ways


This disk was automatically cracked by
Passport. Here is the transcript:

                 --v--

READING FROM S6,D1
T00,S00 FOUND DOS 3.3 BOOTLOADER
USING DISK'S OWN RWTS
WRITING TO S5,D2
SWITCHING TO BUILT-IN RWTS
T00,S03,$55: AA -> D5
T00,S03,$5F: D5 -> AA
T00,S06,$7A: AA -> D5
T00,S06,$7F: D5 -> AA
CRACK COMPLETE.

                 --^--

More information and source code is
available at
https://archive.org/details/Passport4am

Quod erat liberand one more thing...

                   ~

               Chapter 1
      Oh What Fresh Hell Is This


My original disk is labeled thusly:

"THIS DISKETTE HAS A LIMITED NUMBER OF
BOOTS. IT IS TO BE USED ONLY AS A
BACKUP COPY."

And, true to form, every time you boot
the disk, it displays a counter that
tells you how many boots you have left.

                 --v--

  WARNING:  THIS DISKETTE MAY ONLY BE
            BOOTED 042 MORE TIMES.


      PRESS SPACE BAR TO CONTINUE

                 --^--

Also, if you try to write-protect the
disk, it says "PLEASE REMOVE THE WRITE-
PROTECT STICKER" and refuses to
continue until it can write to the disk
to decrement the counter.

So that's annoying.

Turning to my trusty Disk Fixer sector
editor, the bootloader appears to be
fairly close to the standard DOS 3.3
boot code. It starts loading DOS from
T02,S0D instead of T02,S04, presumably
so it all fits on tracks 1 and 2, which
used a different prologue sequence
before each sector. (Passport fixed
that for us. Hooray!)

                 --v--

T00,S01
----------- DISASSEMBLY MODE ----------
0000:8E E9 37       STX   $37E9
0003:8E F7 37       STX   $37F7
0006:A9 01          LDA   #$01
0008:8D F8 37       STA   $37F8
000B:8D EA 37       STA   $37EA
000E:AD E0 37       LDA   $37E0
0011:8D E1 37       STA   $37E1
0014:A9 02          LDA   #$02  ; track
0016:8D EC 37       STA   $37EC
0019:A9 0D          LDA   #$0D  ; sectr
001B:8D ED 37       STA   $37ED
001E:AC E7 37       LDY   $37E7 ; #$36
0021:88             DEY
0022:8C F1 37       STY   $37F1 ; addr
0025:A9 01          LDA   #$01
0027:8D F4 37       STA   $37F4
002A:8A             TXA
002B:4A             LSR
002C:4A             LSR
002D:4A             LSR
002E:4A             LSR
002F:AA             TAX
0030:A9 00          LDA   #$00
0032:9D F8 04       STA   $04F8,X
0035:9D 78 04       STA   $0478,X
0038:20 93 37       JSR   $3793
003B:A2 FF          LDX   #$FF
003D:9A             TXS
003E:8E EB 37       STX   $37EB
0041:4C C8 3F       JMP   $3FC8
0044:20 89 FE       JSR   $FE89
0047:4C 00 18       JMP   $1800 ; huh?!

                 --^--

The final jump (offset $0047) is odd.
I would expect it to jump to $1B03 so
it can relocate DOS to higher memory
($9D00 on a machine with at least 48K).
But instead we're calling a non-
standard entry point at $1800.

If T02,S0D is loaded at $3500, then
$1800 is T01,S00.

                 --v--

T01,S00
----------- DISASSEMBLY MODE ----------
; munge reset vector so <Ctrl-Reset>
; will reboot
0000:AD F3 03       LDA   $03F3
0003:8D F4 03       STA   $03F4

; TEXT / PR#0 / IN#0 / HOME
0006:20 2F FB       JSR   $FB2F
0009:20 93 FE       JSR   $FE93
000C:20 89 FE       JSR   $FE89
000F:20 58 FC       JSR   $FC58

0012:A9 0A          LDA   #$0A
0014:85 25          STA   $25
0016:2C 2A 00       BIT   $002A

; decrements a value inside the opcode
; directly above ("BIT")
0019:CE 17 18       DEC   $1817

; if not zero yet, skip ahead
001C:D0 05          BNE   $0023

; set a flag on the other value inside
; that dummy opcode
001E:A9 80          LDA   #$80
0020:8D 18 18       STA   $1818

; set up a write command
0023:A2 02          LDX   #$02
0025:8E F4 37       STX   $37F4

; track 1
0028:CA             DEX
0029:8E EC 37       STX   $37EC

; sector 0 (that's where this code is
; stored -- we're writing ourselves,
; including the changes we just made
; to $1817 and $1818)
002C:CA             DEX
002D:8E ED 37       STX   $37ED
0030:8E EB 37       STX   $37EB
0033:EE F1 37       INC   $37F1

; call RWTS to write this sector back
; to disk
0036:A0 E8          LDY   #$E8
0038:A9 37          LDA   #$37
003A:20 B5 37       JSR   $37B5

; if write succeeded, skip ahead
003D:90 14          BCC   $0053

; check error code in RWTS parameter
; table
003F:AD F5 37       LDA   $37F5

; error $10 = write-protected
0042:C9 10          CMP   #$10
0044:D0 0A          BNE   $0050

; display "PLEASE REMOVE THE WRITE-
PROTECT STICKER" message (stored at
; $189A)
0046:A0 9A          LDY   #$9A
0048:A9 18          LDA   #$18
004A:20 99 19       JSR   $1999
004D:20 4E 19       JSR   $194E

; (not shown) reboots
0050:4C 8A 19       JMP   $198A

; Execution continues here (from $183D)
; if we successfully wrote the counter
; back to disk. Now check that flag at
; $1818
0053:2C 18 18       BIT   $1818

; if flag was not set, skip ahead
0056:30 21          BMI   $0079

; display first few lines of "WARNING"
; message (string is stored at $18C4)
0058:A0 C4          LDY   #$C4
005A:A9 18          LDA   #$18
005C:20 99 19       JSR   $1999

; display actual counter, converted to
; base 10
005F:AE 17 18       LDX   $1817
0062:CA             DEX
0063:86 44          STX   $44
0065:A2 00          LDX   #$00
0067:86 45          STX   $45
0069:20 42 2E       JSR   $2E42

; display the rest of the "WARNING"
; message (stored at $18FB)
006C:A0 FB          LDY   #$FB
006E:A9 18          LDA   #$18
0070:20 99 19       JSR   $1999

; wait for key
0073:20 4E 19       JSR   $194E

; continue to DOS initialization
0076:4C 03 1B       JMP   $1B03

; Execution continues here (from $1856)
; if the flag at $1818 was set. We're
; turning on the drive motor manually,
; which is never a good sign.
0079:AE E9 37       LDX   $37E9
007C:BD 89 C0       LDA   $C089,X

; seek to track $11 (disk catalog)
007F:A9 11          LDA   #$11
0081:20 5A 3E       JSR   $3E5A

; overwrite entire track with garbage
; (whatever happens to be in memory)
0084:20 0D 3F       JSR   $3F0D

; turn off drive motor
0087:AE E9 37       LDX   $37E9
008A:BD 88 C0       LDA   $C088,X

; display message "THIS BACKUP DISK HAS
; BEEN USED 50 TIMES AND CAN NO LONGER
; BE BOOTED." (string stored at $1908)
008D:A0 08          LDY   #$08
008F:A9 19          LDA   #$19
0091:20 99 19       JSR   $1999

; wait for key
0094:20 4E 19       JSR   $194E

; reboot
0097:4C 8A 19       JMP   $198A

                 --^--

So, once the counter hits 0, this final
routine trashes the disk catalog so you
can't use it even if you manage to hack
into this routine to reset the counter.

Charming.

On the bright side, this entire mess
appears to be self-contained; there
would be no ill effects to skipping it
altogether. Popping the stack all the
way back to the bootloader, changing
the "JMP $1800" to "JMP $1B03" would go
straight to loading DOS and running the
actual program. Not only will it not
decrement the counter, it won't even
display it.

T00,S01,$48: 0018 -> 031B

]PR#6
...boots and runs and it is glorious...

Quod erat liberandum.

---------------------------------------
A 4am crack                    No. 1062
------------------EOF------------------
